package com.jwsoft.manager.core.integration.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bifang.engine.assistant.core.annotation.ApiService;
import com.bifang.engine.assistant.core.annotation.OpApi;
import com.bifang.engine.assistant.core.annotation.SaveOplog;
import com.bifang.engine.assistant.core.enums.AuTypeEnum;
import com.bifang.engine.assistant.core.enums.BoolEnum;
import com.bifang.engine.assistant.core.enums.FuncTypeEnum;
import com.bifang.engine.assistant.core.exception.AppException;
import com.bifang.engine.assistant.core.utils.SessionUtil;
import com.bifang.engine.data.core.util.PagerUtil;
import com.bifang.module.base.common.vo.dict.DictQueryVO;
import com.bifang.module.base.common.vo.dict.SelectVO;
import com.bifang.module.base.common.vo.excel.ExcelModelVO;
import com.bifang.module.base.common.vo.excel.ExcelVO;
import com.bifang.module.base.core.helper.ExcelCommonHelper;
import com.bifang.module.base.core.integration.DictIntegration;
import com.bifang.module.base.core.integration.ExcelIntegration;
import com.bifang.module.system.core.dao.service.ExcelModelService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jwsoft.manager.common.vo.eduSyncJhApplyError.EduSyncJhApplyErrorKeyVO;
import com.jwsoft.manager.common.vo.eduSyncJhApplyError.EduSyncJhApplyErrorQueryVO;
import com.jwsoft.manager.common.vo.eduSyncJhApplyError.EduSyncJhApplyErrorVO;
import com.jwsoft.manager.core.dao.model.EduSyncJhApplyError;
import com.jwsoft.manager.core.dao.service.EduSyncJhApplyErrorService;
import com.jwsoft.manager.core.integration.EduSyncJhApplyErrorIntegration;
import com.jwsoft.manager.core.integration.EduSyncJhImportBatchIntegration;
import com.jwsoft.manager.core.util.EduDesensitizeUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 金华市报名专库同步导入错误表业务实现类
 *
 * @author zhiyuan
 * @since 2024-04-10
 */
@ApiService(funcCode = "syncJhApplyError", title = "金华市报名专库同步导入错误表")
public class EduSyncJhApplyErrorIntegrationImpl implements EduSyncJhApplyErrorIntegration {

    @Autowired
    public EduSyncJhApplyErrorService eduSyncJhApplyErrorService;

    @Autowired
    private EduSyncJhImportBatchIntegration importBatchIntegration;
    @Autowired
    private ExcelIntegration excelIntegration;


    @Autowired
    private ExcelCommonHelper excelCommonHelper;

    @Autowired
    private DictIntegration dictIntegration;
    @Value("${spring.servlet.multipart.location}")
    private String tempPath;

    @Autowired
    public ExcelModelService excelModelService;


    @Override
    @OpApi(funcCode = "syncJhApplyError0001", title = "金华市报名专库同步导入错误表分页查询", funcType = FuncTypeEnum.query,checkPrivilege = BoolEnum.FALSE)
    public PageInfo<EduSyncJhApplyErrorVO> getList(EduSyncJhApplyErrorQueryVO vo) {
        // 开启分页
        if (vo.getPageNum() == null || vo.getPageSize() == null) {
            //如果不传入分页参数，默认最大取1000条
            vo.setPageNum(1);
            vo.setPageSize(1000);
        }
        Boolean desensitizeFlag = vo.getDesensitizeFlag();
        if (desensitizeFlag == null){
            desensitizeFlag = true;
        }
        PageHelper.startPage(vo.getPageNum(),vo.getPageSize());
        QueryWrapper<EduSyncJhApplyError> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(vo.getImportBatchId() != null,EduSyncJhApplyError::getImportBatchId,vo.getImportBatchId())
                .eq(StringUtils.isNotBlank(vo.getAreaCode()),EduSyncJhApplyError::getAreaCode,vo.getAreaCode());
        List<EduSyncJhApplyError> list = eduSyncJhApplyErrorService.list(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            // 判断是否为空，为空则返回空参数
            return PagerUtil.createEmptyPagerInfo(vo.getPageNum(), vo.getPageSize());
        }
        // 不为空则获取分页结果
        PageInfo<EduSyncJhApplyError> pageInfo = new PageInfo<>(list);
        // 返回参数需要通过common层的vo实体类，用该方法可以批量转换
        List<EduSyncJhApplyErrorVO> resultList = Convert.toList(EduSyncJhApplyErrorVO.class, pageInfo.getList());
        // 转义数据字典值
        // dictHelper.valueToName(resultList, Arrays.asList(DemoDictEnum.values()));
        if (desensitizeFlag) {
            for (EduSyncJhApplyErrorVO errorVO : resultList) {
                errorVO.setName(EduDesensitizeUtil.desensitizeFullName(errorVO.getName()));
                errorVO.setIdcard(EduDesensitizeUtil.desensitizeIdcard(errorVO.getIdcard()));
            }
        }
        return PagerUtil.parsePagerVo(resultList, pageInfo);
    }

    @Override
    @OpApi(funcCode = "syncJhApplyError0002", title = "金华市报名专库同步导入错误表根据主键查询详情", funcType = FuncTypeEnum.query,checkPrivilege = BoolEnum.FALSE)
    public EduSyncJhApplyErrorVO getById(EduSyncJhApplyErrorKeyVO vo) {
        EduSyncJhApplyError entity = eduSyncJhApplyErrorService.getById(vo.getJhApplyId());
        if (ObjectUtils.isEmpty(entity)) {
            throw new AppException("查询不到详细信息!");
        }
        EduSyncJhApplyErrorVO result = Convert.convert(EduSyncJhApplyErrorVO.class, entity);
        return result;
    }
    /** 保存前统一校验*/
    @Override
    @OpApi(funcCode = "syncJhApplyError0003", title = "金华市报名专库同步导入错误表保存前校验", funcType = FuncTypeEnum.other ,checkPrivilege = BoolEnum.FALSE)
    public void checkSave(EduSyncJhApplyErrorVO vo) {
        //主键为空为新增校验

        //主键不为空为修改校验
    }

    @Override
    @OpApi(funcCode = "syncJhApplyError0004", title = "金华市报名专库同步导入错误表新增", funcType = FuncTypeEnum.insert)
    @SaveOplog(
            operationType = "syncJhApplyError0004",
            operationName = "金华市报名专库同步导入错误表新增",
            dataType = "jhApplyId",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public EduSyncJhApplyErrorVO add(EduSyncJhApplyErrorVO vo) {
        //保存前校验
        checkSave(vo);
        //保存数据
        EduSyncJhApplyError entity = Convert.convert(EduSyncJhApplyError.class, vo);
        eduSyncJhApplyErrorService.save(entity);
        //将主键设置回vo使操作日志可以取到
        vo.setJhApplyId(entity.getJhApplyId());
        return vo;
    }

    @Override
    @OpApi(funcCode = "syncJhApplyError0005", title = "金华市报名专库同步导入错误表修改", funcType = FuncTypeEnum.update)
    @SaveOplog(
            operationType = "syncJhApplyError0005",
            operationName = "金华市报名专库同步导入错误表修改",
            dataType = "jhApplyId",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public EduSyncJhApplyErrorVO edit(EduSyncJhApplyErrorVO vo) {
        if (ObjectUtils.isEmpty(vo.getJhApplyId())) {
            throw new AppException("传入需要修改的主键不能为空!");
        }
        EduSyncJhApplyError oldEntity = eduSyncJhApplyErrorService.getById(vo.getJhApplyId());
        if (ObjectUtils.isEmpty(oldEntity)) {
            throw new AppException("查询不到需要修改的信息!");
        }
        //保存前校验
        checkSave(vo);
        //保存数据
        EduSyncJhApplyError entity = Convert.convert(EduSyncJhApplyError.class, vo);
        eduSyncJhApplyErrorService.updateById(entity);
        return vo;
    }

    @Override
    @OpApi(funcCode = "syncJhApplyError0006", title = "金华市报名专库同步导入错误表根据主键删除", funcType = FuncTypeEnum.delete)
    @SaveOplog(
            operationType = "syncJhApplyError0006",
            operationName = "金华市报名专库同步导入错误表删除",
            dataType = "jhApplyId",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public void del(EduSyncJhApplyErrorKeyVO vo) {
        if (ObjectUtils.isEmpty(vo.getJhApplyId())) {
            throw new AppException("传入需要删除的数据主键不能为空!");
        }
        EduSyncJhApplyError entity = eduSyncJhApplyErrorService.getById(vo.getJhApplyId());
        if (ObjectUtils.isEmpty(entity)) {
            throw new AppException("未找到需要删除的信息!");
        }
        eduSyncJhApplyErrorService.removeById(vo.getJhApplyId());
    }

    @Override
    @OpApi(funcCode = "syncJhApplyError0007",
            title = "导出错误数据", funcType = FuncTypeEnum.other, checkPrivilege = BoolEnum.FALSE)
    public void exportInfo(EduSyncJhApplyErrorQueryVO vo, HttpServletResponse response) {
        if (ObjectUtils.isEmpty(vo.getModelCode())) {
            throw new AppException("请传入模板编码!  ");
        }
        if (ObjectUtils.isEmpty(vo.getImportBatchId())){
            throw new AppException("请传入导入批次号! ");
        }
        if (StringUtils.isBlank(vo.getAreaCode())){
            vo.setAreaCode(SessionUtil.getAreaCode());
        }
        ExcelVO excelVO = new ExcelVO();
        excelVO.setModelCode(vo.getModelCode());
        Map<String, List<SelectVO>> dictMap = new HashMap<>();
        //设置学段
        dictMap.put("schoolCategory", importBatchIntegration.getSchoolCategory());
        //设置民族下拉框信息
        dictMap.put("nation", importBatchIntegration.getNationDict());
        //设置身份证类型下拉框信息
        dictMap.put("cardType", importBatchIntegration.getCardTypeDict());
        //设置性别
        dictMap.put("sex", importBatchIntegration.getSexDict());
        //获取户口类型
        dictMap.put("householdType", importBatchIntegration.getHouseHoldTypeDict());
        //获取和子女关系字典列表
        List<SelectVO> relation = importBatchIntegration.getRelationDict();
        dictMap.put("masterGuardianRelation", relation);
        dictMap.put("slaveGuardianRelation", relation);
        excelVO.setDictMap(dictMap);
        ExcelModelVO excelModelVO = excelIntegration.getModel(excelVO);

        String destFilePath = this.tempPath + "/" + IdUtil.fastSimpleUUID() + "." + excelModelVO.getExcelType();
        int pageNum = 1;
        //如果数据为空，就下载模板给他
        if(queryCountByVO(vo) == 0){
            excelCommonHelper.downloadModel(excelModelVO,null,response);
            return;
        }
        setData(excelModelVO, null, destFilePath, vo, pageNum);
        String fileName = "金华市报名同步错误数据" + DateUtil.today();
        if (StringUtils.isBlank(fileName)) {
            fileName =
                    excelModelVO.getModelName()
                            + "_"
                            + DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_PATTERN)
                            + "."
                            + (StringUtils.isBlank(excelModelVO.getExcelType())
                            ? "xls"
                            : excelModelVO.getExcelType());
        }
        File file = FileUtil.file(destFilePath);
        BufferedInputStream in = null;
        try {
            in = FileUtil.getInputStream(file);
            ServletUtil.write(response, in, "application/octet-stream;charset=utf-8", fileName);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            FileUtil.del(destFilePath);
        }
    }

    private Integer queryCountByVO(EduSyncJhApplyErrorQueryVO vo) {
        QueryWrapper<EduSyncJhApplyError> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(vo.getImportBatchId() != null,EduSyncJhApplyError::getImportBatchId,vo.getImportBatchId())
                .eq(StringUtils.isNotBlank(vo.getAreaCode()),EduSyncJhApplyError::getAreaCode,vo.getAreaCode());
        return Math.toIntExact(eduSyncJhApplyErrorService.count(queryWrapper));
    }

    private void setData(ExcelModelVO excelModelVO, ExcelWriter excelWriter, String destFilePath, EduSyncJhApplyErrorQueryVO vo, int pageNum) {
        vo.setPageNum(pageNum);
        vo.setPageSize(500);
        boolean closeFlag = false;
        try {
            PageInfo<EduSyncJhApplyErrorVO> pageInfo = getList(vo);
            String total = String.valueOf(pageInfo.getTotal());
            List<Map<String, Object>> list = new ArrayList<>();
            if (!CollectionUtils.isEmpty(pageInfo.getList())) {
                for (EduSyncJhApplyErrorVO errorVO : pageInfo.getList()) {
                    //将数据字典的key 转换为value
                    dictKeyToValue(errorVO);
                    list.add(BeanUtil.beanToMap(errorVO, false, true));
                }
            }
            if (pageNum == 1) {
                if (excelWriter == null) {
                    excelWriter = excelCommonHelper.createExcelWriter(excelModelVO, destFilePath, Integer.parseInt(total));
                }
                excelCommonHelper.writeMap(excelWriter, list);
            } else {
                excelCommonHelper.writeMap(excelWriter, list);
            }
            if (pageInfo.isHasNextPage()) {
                pageNum = pageNum + 1;
                setData(excelModelVO, excelWriter, destFilePath, vo, pageNum);
            } else {
                closeFlag = true;
            }
        } catch (AppException appEx) {
            throw appEx;
        } catch (Exception e) {
            throw new AppException("调用自定义写入服务异常:" + e.getMessage());
        } finally {
            if (closeFlag && excelWriter != null) {
                excelWriter.close();
            }
        }
    }

    private void dictKeyToValue(EduSyncJhApplyErrorVO errorVO) {
        //转换学段
        if (StringUtils.isNotBlank(errorVO.getSchoolCategory())) {
            DictQueryVO dictQueryVO = new DictQueryVO();
            dictQueryVO.setDictField("SCHOOLCATEGORY");
            dictQueryVO.setDictKey(errorVO.getSchoolCategory());
            String schoolCategory = dictIntegration.getValue(dictQueryVO);
            errorVO.setSchoolCategory(schoolCategory);
        }

        //转换证件类型
        if (StringUtils.isNotBlank(errorVO.getCardType())) {
            DictQueryVO dictQueryVO = new DictQueryVO();
            dictQueryVO.setDictField("CARDTYPE");
            dictQueryVO.setDictKey(errorVO.getCardType());
            String cardType = dictIntegration.getValue(dictQueryVO);
            errorVO.setCardType(cardType);
        }

        //转换性别
        if (StringUtils.isNotBlank(errorVO.getSex())) {
            DictQueryVO dictQueryVO = new DictQueryVO();
            dictQueryVO.setDictField("SEXZJ");
            dictQueryVO.setDictKey(errorVO.getSex());
            String sex = dictIntegration.getValue(dictQueryVO);
            errorVO.setSex(sex);
        }

        //转换民族
        if (StringUtils.isNotBlank(errorVO.getNation())) {
            DictQueryVO dictQueryVO = new DictQueryVO();
            dictQueryVO.setDictField("NATION");
            dictQueryVO.setDictKey(errorVO.getNation());
            String nation = dictIntegration.getValue(dictQueryVO);
            errorVO.setNation(nation);
        }

        //转换户口类型
        if (StringUtils.isNotBlank(errorVO.getHouseholdType())) {
            DictQueryVO dictQueryVO = new DictQueryVO();
            dictQueryVO.setDictField("JHHOUSEHOLDTYPE");
            dictQueryVO.setDictKey(errorVO.getHouseholdType());
            String householdType = dictIntegration.getValue(dictQueryVO);
            errorVO.setHouseholdType(householdType);
        }

        //转换监护人1 与学生关系
        if (StringUtils.isNotBlank(errorVO.getMasterGuardianRelation())) {
            DictQueryVO dictQueryVO = new DictQueryVO();
            dictQueryVO.setDictField("GUARDIANRELATION");
            dictQueryVO.setDictKey(errorVO.getMasterGuardianRelation());
            String guardian1Relation = dictIntegration.getValue(dictQueryVO);
            errorVO.setMasterGuardianRelation(guardian1Relation);
        }

        //转换监护人2 与学生关系
        if (StringUtils.isNotBlank(errorVO.getSlaveGuardianRelation())) {
            DictQueryVO dictQueryVO = new DictQueryVO();
            dictQueryVO.setDictField("GUARDIANRELATION");
            dictQueryVO.setDictKey(errorVO.getSlaveGuardianRelation());
            String guardian2Relation = dictIntegration.getValue(dictQueryVO);
            errorVO.setSlaveGuardianRelation(guardian2Relation);
        }
        //时间戳转换为日期格式
        if (errorVO.getApplyTime() != null) {
            Date date = new Date(errorVO.getApplyTime());
            SimpleDateFormat sdf  = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            // 将Date对象格式化为字符串
            String applyDate = sdf.format(date);
            errorVO.setApplyDate(applyDate);
        }
    }


}
